package com.xjgz.aio.socket.pro.extension.plugins;

import com.xjgz.aio.socket.buffer.BufferPagePool;
import com.xjgz.aio.socket.pro.timer.HashedWheelTimer;
import com.xjgz.aio.socket.pro.timer.TimerTask;
import com.xjgz.aio.socket.transport.AioQuickServer;

import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;

/**
 * 内存页监控插件
 *
 * @param <T>
 */
public class BufferPageMonitorPlugin<T> extends AbstractPlugin<T> {

    private int seconds;

    private final AioQuickServer server;

    private TimerTask future;

    public BufferPageMonitorPlugin(AioQuickServer server, int seconds) {
        this.seconds = seconds;
        this.server = server;
        init();
    }

    private void init() {
        future = HashedWheelTimer.DEFAULT_TIMERS.scheduleWithFixedDelay(() -> {
            if (server == null) {
                System.err.println("unknow server or client need to monitor!");
                shutdown();
                return;
            }
            try {
                Field bufferPoolField = AioQuickServer.class.getDeclaredField("writeBufferPool");
                bufferPoolField.setAccessible(true);
                BufferPagePool writeBufferPool = (BufferPagePool) bufferPoolField.get(server);
                if (writeBufferPool == null) {
                    System.err.println("server maybe has not started yet!");
                    shutdown();
                    return;
                }

                Field readBufferPoolField = AioQuickServer.class.getDeclaredField("readBufferPool");
                readBufferPoolField.setAccessible(true);
                BufferPagePool readBufferPool = (BufferPagePool) readBufferPoolField.get(server);
                if (readBufferPool != null && readBufferPool != writeBufferPool) {
                    dumpBufferPool(readBufferPool);
                    dumpBufferPool(writeBufferPool);
                } else {
                    dumpBufferPool(writeBufferPool);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, seconds, TimeUnit.SECONDS);
    }

    private static void dumpBufferPool(BufferPagePool writeBufferPool) {
        System.out.println(writeBufferPool);
    }

    private void shutdown() {
        if (future != null) {
            future.cancel();
            future = null;
        }
    }
}
